﻿using DevExpress.Mvvm;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using PlaceOrder_Core.Models.QuanYi;
using PlaceOrder_Core.PlaceOrderModels;
using PlaceOrder_Core.Services.Instances;
using PlaceOrder_Core.Services.Interfaces;
using PlaceOrder_Shared.Models.Trade;
using Prism.DryIoc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;
using PlaceOrder_Core.Helper;
using PlaceOrder_Client.Models.Common;

namespace PlaceOrder_Client.ViewModels
{
    public class DailyOrderStatusViewModel:BindableBase
    {
        #region 依赖属性
        #region 第一列
        /// <summary>
        /// 加权限仓
        /// </summary>
        private decimal maxVolume;

        public decimal MaxVolume
        {
            get { return maxVolume; }
            set { maxVolume = value; RaisePropertiesChanged(); }
        }


        /// <summary>
        /// 允许总亏损
        /// </summary>
        private decimal minProfitAllTime;

        public decimal MinProfitAllTime
        {
            get { return minProfitAllTime; }
            set { minProfitAllTime = value; RaisePropertiesChanged(); }
        }

        /// <summary>
        /// 当前总盈亏
        /// </summary>
        private decimal profitAllTime;

        public decimal ProfitAllTime
        {
            get { return profitAllTime; }
            set { profitAllTime = value; RaisePropertiesChanged(); }
        }

        /// <summary>
        /// 当前实盈
        /// </summary>
        private decimal solidProfit;

        public decimal SolidProfit
        {
            get { return solidProfit; }
            set { solidProfit = value; RaisePropertiesChanged(); }
        }
        #endregion

        #region 第二列
        /// <summary>
        /// 加权买仓
        /// </summary>
        private decimal currentBid;

        public decimal CurrentBid
        {
            get { return currentBid; }
            set { currentBid = value; RaisePropertiesChanged(); }
        }

        /// <summary>
        /// 允许日亏损
        /// </summary>
        private decimal minProfitDaily;

        public decimal MinProfitDaily
        {
            get { return minProfitDaily; }
            set { minProfitDaily = value; RaisePropertiesChanged(); }
        }

        /// <summary>
        /// 当日浮盈
        /// </summary>
        private decimal floatProfit;

        public decimal FloatProfit
        {
            get { return floatProfit; }
            set { floatProfit = value; RaisePropertiesChanged(); }
        }


        #endregion

        #region 第三列
        /// <summary>
        /// 加权卖仓
        /// </summary>
        private decimal currentOffer;

        public decimal CurrentOffer
        {
            get { return currentOffer; }
            set { currentOffer = value; RaisePropertiesChanged(); }
        }

        // <summary>
        /// 允许日回撤
        /// </summary>
        private decimal minBackDaily;

        public decimal MinBackDaily
        {
            get { return minBackDaily; }
            set { minBackDaily = value; RaisePropertiesChanged(); }
        }

        // <summary>
        /// 当日回撤
        /// </summary>
        private decimal back;

        public decimal Back
        {
            get { return back; }
            set { back = value; RaisePropertiesChanged(); }
        }

        // <summary>
        /// 当日剩余笔数
        /// </summary>
        private decimal rest;

        public decimal Rest
        {
            get { return rest; }
            set { rest = value; RaisePropertiesChanged(); }
        }
        #endregion


        /// <summary>
        /// 手续费
        /// </summary>
        private decimal totalFee;

        public decimal TotalFee
        {
            get { return totalFee; }
            set { totalFee = value; RaisePropertiesChanged(); }
        }


        /// <summary>
        /// 当前可买
        /// </summary>
        private decimal limitBid;

        public decimal LimitBid
        {
            get { return limitBid; }
            set { limitBid = value;RaisePropertiesChanged(); }
        }

        /// <summary>
        /// 当前可卖
        /// </summary>
        private decimal limitOffer;

        public decimal LimitOffer
        {
            get { return limitOffer; }
            set { limitOffer = value; RaisePropertiesChanged(); }
        }
        #endregion

        #region 静态变量
        public static List<QuanyiClientTradeClass> OrderList = new List<QuanyiClientTradeClass>();
     
        #endregion
        private readonly IDailyData _dailyData;

        private TSInfoRow TsInfo;
        private readonly DispatcherTimer _timer;
        
        public DailyOrderStatusViewModel(IDailyData dailyData)
        {
            _dailyData = dailyData;
            InitValue();


            // 初始化定时器
            //_timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
            //_ = StartTimerAsync();
            RefreshDailyStatus();
            _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromSeconds(6); // 设置30秒间隔
            _timer.Tick += async (sender, e) => await RefreshDailyStatus();
            _timer.Start();
        }
        public void SetTsInfo(TSInfoRow tsinfo)
        {
            this.TsInfo = tsinfo;
        }
       

        #region 方法
        private int TKNVolume = 0, GVNVolume = 0, TKNWaitingVolume = 0, GVNWaitingVolume = 0, TKNRealVolume = 0, GVNRealVolume = 0;
        private int TotalRealVolume = 0;
        private decimal TotalProfit = 0;
        private decimal DailyProfit = 0;
        private decimal DailyDrawDown = 0;
        private decimal DynProfit = 0;

        private int CurrentMaxVolume = 0;
        private int CurrentMaxRealVolume = 0;
        private decimal BrokeRage = 0.0003M; //经纪费率（佣金率），即交易金额的 0.03%
        private TradeSimUser TradeUser = new TradeSimUser();
        /// <summary>
        /// 初始化信息
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void InitValue()
        {
            //OrderList = _dailyData.GetQuanyiSimulationTrades();0831
            //TradeUser = _dailyData.GetTradeSimSingleUser(UserHelper.UserID);
        }
        private void UpdateProfit()
        {
            //LDrawDown.Text = DailyDrawDown.ToString() + "万";
            //LRestCredit = TradeUser.TotalAllowedMaxOpen.ToString() + "万";
            //LTKNRealVolume = TKNRealVolume.ToString() + "万";
            //LGVNRealVolume = GVNRealVolume.ToString() + "万";
            
            //LMaxTKNVolume = "买入 " + TKNVolume.ToString() + "万";
            //LMaxGVNVolume = "卖出 " + GVNVolume.ToString() + "万";
            //LProfit = TotalProfit.ToString() + "万";
            //LDynProfit = DynProfit.ToString() + "万";
            //LMaxSingleOpen = TradeUser.TotalAllowedSingleOpen.ToString() + "万";
            //LDailyProfit = DailyProfit.ToString() + "万";
            //LMaxLoss = (-TradeUser.AllowedTotalLoss).ToString() + "万";
            //LDailyLoss= (-TradeUser.AllowedDailyLoss).ToString() + "万";
            //LMaxDrawDown = (-TradeUser.AllowedDailyLoss * 1.6M).ToString() + "万";
            //lRealVolume.Text = ((TradeUser.TotalAllowedMaxOpen - TotalRealVolume) / 500 * 500).ToString() + "万";
        }

        /// <summary>
        /// 计算当天回撤量，以及当天剩余可用仓位等信息
        /// </summary>
        private void CalcDailyDrawDown()
        {
            TKNVolume = 0;
            GVNVolume = 0;
            TKNWaitingVolume = 0;
            GVNWaitingVolume = 0;
            TKNRealVolume = 0;
            GVNRealVolume = 0;
            if (TradeUser.DrawDownDate < DateOnly.FromDateTime(DateTime.Now))
            {
                TradeUser.DrawDownDate = DateOnly.FromDateTime(DateTime.Now);
                TradeUser.DailyDrawDown = 0;
                _dailyData.UpdateQuanyiSimUserDrawDown(TradeUser);
            }

            if (TsInfo.PVBP == 0)
            {
                TsInfo.PVBP = DataHelper.DefaultPVBP;
            }

            TotalRealVolume = 0;
            if (OrderList.Count > 0)
            {
                List<decimal> profits = new List<decimal>();
                List<string> OnHoldingTsCodes = OrderList.GroupBy(x => x.TsCode).Select(x => x.Key).ToList();
                int TKNOnHolding, GVNOnHolding, TKNOnWaitting, GVNOnWaitting;
                foreach (string t in OnHoldingTsCodes)
                {
                    TSInfoRow ts = _dailyData.GetBondByCode(t);
                    TKNOnHolding = OrderList.Where(x => x.TsCode == t & x.Status == QuanyiClientTradeClass.TradeStatus.Traded & x.DealType == "TKN").Sum(x => x.OnHoldVolume);
                    GVNOnHolding = OrderList.Where(x => x.TsCode == t & x.Status == QuanyiClientTradeClass.TradeStatus.Traded & x.DealType == "GVN").Sum(x => x.OnHoldVolume);
                    TKNOnWaitting = OrderList.Where(x => x.TsCode == t & x.Status <= QuanyiClientTradeClass.TradeStatus.Withdrawing & x.DealType == "TKN").Sum(x => x.Volume);
                    GVNOnWaitting = OrderList.Where(x => x.TsCode == t & x.Status <= QuanyiClientTradeClass.TradeStatus.Withdrawing & x.DealType == "GVN").Sum(x => x.Volume);
                    TKNWaitingVolume += (int)(TKNOnWaitting * ts.PVBP / DataHelper.DefaultPVBP);
                    GVNWaitingVolume += (int)(GVNOnWaitting * ts.PVBP / DataHelper.DefaultPVBP);
                    int tmpVolume = 0;
                    if (TKNOnHolding == GVNOnHolding)
                    {
                        if (TKNOnWaitting > 0)
                        {
                            TKNRealVolume += (int)(TKNOnWaitting * ts.PVBP / DataHelper.DefaultPVBP);
                        }
                        if (GVNOnWaitting > 0)
                        {
                            GVNRealVolume += (int)(GVNOnWaitting * ts.PVBP / DataHelper.DefaultPVBP);
                        }
                    }
                    else
                    {
                        if (TKNOnHolding > GVNOnHolding)
                        {
                            tmpVolume = TKNOnHolding - GVNOnHolding;
                            TKNRealVolume += (int)((tmpVolume + TKNOnWaitting) * ts.PVBP / DataHelper.DefaultPVBP);
                            if (GVNOnWaitting > TKNOnHolding)
                            {
                                GVNRealVolume += (int)((GVNOnWaitting - TKNOnHolding) * ts.PVBP / DataHelper.DefaultPVBP);
                            }
                        }
                        else
                        {
                            tmpVolume = GVNOnHolding - TKNOnHolding;
                            GVNRealVolume += (int)((tmpVolume + GVNOnWaitting) * ts.PVBP / DataHelper.DefaultPVBP);
                            if (TKNOnWaitting > GVNOnHolding)
                            {
                                TKNRealVolume += (int)((TKNOnWaitting - GVNOnHolding) * ts.PVBP / DataHelper.DefaultPVBP);
                            }
                        }
                    }
                }
                List<QuanyiClientTradeClass> dailyTrades = OrderList.Where(x => (x.TradeDate > DateTime.Now.Date & x.Status >= QuanyiClientTradeClass.TradeStatus.Traded) | x.OnHoldVolume > 0 | x.Status <= QuanyiClientTradeClass.TradeStatus.Withdrawing).OrderBy(x => x.TradeDate).ToList();

                foreach (var t in dailyTrades)
                {
                    profits.Add(dailyTrades.Where(x => x.TradeDate <= t.TradeDate).Sum(x => x.Profit));
                }
                decimal max;
                if (profits.Count == 0)
                {
                    max = 0;
                    DailyDrawDown = 0;
                }
                else
                {
                    max = profits.Max();
                    if (max <= 0)
                    {
                        DailyDrawDown = Math.Round(profits.Min(), 4, MidpointRounding.AwayFromZero);
                    }
                    else
                    {
                        int i = profits.IndexOf(max);
                        profits.RemoveRange(0, i);
                        decimal min = max;
                        if (profits.Count > 0)
                        {
                            min = profits.Min();
                        }
                        DailyDrawDown = Math.Round(min - max, 4, MidpointRounding.AwayFromZero);
                    }
                }


                dailyTrades = null;
            }
            int RestVolume = TradeUser.TotalAllowedMaxOpen - Math.Abs(TotalRealVolume);

            CurrentMaxVolume = (int)(TradeUser.TotalAllowedMaxOpen * DataHelper.DefaultPVBP / TsInfo.PVBP) / 1000 * 1000;
            CurrentMaxRealVolume = (int)(RestVolume * DataHelper.DefaultPVBP / TsInfo.PVBP) / 1000 * 1000;
            TKNVolume = (int)((TradeUser.TotalAllowedMaxOpen - TKNRealVolume) * DataHelper.DefaultPVBP / TsInfo.PVBP) / 1000 * 1000;
            GVNVolume = (int)((TradeUser.TotalAllowedMaxOpen - GVNRealVolume) * DataHelper.DefaultPVBP / TsInfo.PVBP) / 1000 * 1000;
            //最小下单量为2000，如当前可用仓位小于2000，则不允许下单
            if (CurrentMaxRealVolume < 2000)
            {
                CurrentMaxRealVolume = 0;
            }
            if (CurrentMaxVolume < 2000)
            {
                CurrentMaxVolume = 0;
            }
            if (TKNVolume < 2000)
            {
                TKNVolume = 0;
            }
            if (GVNVolume < 2000)
            {
                GVNVolume = 0;
            }
            if (DailyDrawDown < TradeUser.DailyDrawDown)
            {
                TradeUser.DailyDrawDown = DailyDrawDown;
                _dailyData.UpdateQuanyiSimUserDrawDown(TradeUser);
            }
            else
            {
                DailyDrawDown = TradeUser.DailyDrawDown;
            }
        }


        private decimal? previousFloatProfit = null; // 存储上一次的 FloatProfit 值

        private async Task RefreshDailyStatus() // 声明为异步方法
        {
            try
            {
                var handler = new HttpClientHandler
                {
                    ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => true,
                    SslProtocols = System.Security.Authentication.SslProtocols.Tls12
                };

                using (var client = new HttpClient(handler))
                {
                    client.DefaultRequestHeaders.Add("User-Agent", "BondHelper");
                    client.DefaultRequestHeaders.Accept.TryParseAdd("application/json");
                    client.DefaultRequestHeaders.Add("Authorization", UserHelper.Token);

                    var data = new { userId = UserHelper.UserID };
                    string json = JsonConvert.SerializeObject(data);
                    HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
                    HttpResponseMessage res = await client.PostAsync($"{DataHelper.BaseConfig.HttpUrl}/tradeamountlimit/userlatestriskinfo", content);

                    if (res.StatusCode == HttpStatusCode.OK)
                    {
                        string tmp = await res.Content.ReadAsStringAsync();
                        JObject jsonObj = JObject.Parse(tmp);
                        JObject valueObj = (JObject)jsonObj["value"];

                        int maxvolume = (int)valueObj["maxVolume"];
                        int currentBid = (int)valueObj["currentBid"];
                        int currentOffer = (int)valueObj["currentOffer"];
                        decimal minProfitAlltime = (decimal)valueObj["minProfitAlltime"];
                        decimal minProfitDaily = (decimal)valueObj["minProfitDaily"];
                        decimal minBackDaily = (decimal)valueObj["minBackDaily"];
                        decimal profitAlltime = (decimal)valueObj["profitAlltime"];
                        decimal solidProfit = (decimal)valueObj["solidProfit"];
                        decimal floatProfit = (decimal)valueObj["floatProfit"];
                        decimal totalFee = (decimal)valueObj["totalFee"];
                        int back = (int)valueObj["back"];
                        int limitBid = (int)valueObj["limitBid"];
                        int limitOffer = (int)valueObj["limitOffer"];

                        // 判断数据是否变化
                        bool shouldUpdateUI = previousFloatProfit.HasValue && previousFloatProfit.Value != floatProfit ||
                                               this.MaxVolume != maxvolume ||
                                               this.MinProfitAllTime != minProfitAlltime ||
                                               this.ProfitAllTime != profitAlltime ||
                                               this.SolidProfit != solidProfit ||
                                               this.CurrentBid != currentBid ||
                                               this.MinProfitDaily != minProfitDaily ||
                                               this.FloatProfit != floatProfit ||
                                               this.CurrentOffer != currentOffer ||
                                               this.MinBackDaily != minBackDaily ||
                                               this.LimitBid != limitBid ||
                                               this.LimitOffer != limitOffer ||
                                               this.Back != back ||
                                               this.TotalFee != totalFee;

                        if (shouldUpdateUI)
                        {
                            // 更新上一次的 FloatProfit
                           previousFloatProfit = floatProfit;

                            // 使用 Dispatcher.InvokeAsync 刷新 UI
                            //await PrismApplication.Current.Dispatcher.InvokeAsync(() =>
                            {
                                this.MaxVolume = maxvolume;
                                this.MinProfitAllTime = minProfitAlltime;
                                this.ProfitAllTime = profitAlltime;
                                this.SolidProfit = solidProfit;

                                this.CurrentBid = currentBid;
                                this.MinProfitDaily = minProfitDaily;
                                this.FloatProfit = floatProfit;

                                this.CurrentOffer = currentOffer;
                                this.MinBackDaily = minBackDaily;

                                this.LimitBid = limitBid;
                                this.LimitOffer = limitOffer;
                                this.Back = back;

                                this.TotalFee = totalFee;

                                // 发送消息更新
                                Messenger.Default.Send("null", MessageToken.RefreshWeiPing);
                            };
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                AppLog.WriteError("RefreshDailyStatus异常" + ex.Message + ex.StackTrace);
            }
        }

        //private async Task RefreshDailyStatus() // 声明为异步方法
        //{
        //    try
        //    {
        //        var handler = new HttpClientHandler
        //        {
        //            // 如果使用自签名证书，可以使用以下方式忽略证书验证错误（仅用于开发环境）。
        //            ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => true,
        //            SslProtocols = System.Security.Authentication.SslProtocols.Tls12 // 或者指定其他版本
        //        };
        //        using (var client = new HttpClient(handler))
        //        {
        //            client.DefaultRequestHeaders.Add("User-Agent", "BondHelper");
        //            client.DefaultRequestHeaders.Accept.TryParseAdd("application/json");
        //            client.DefaultRequestHeaders.Add("Authorization", UserHelper.Token);

        //            // 创建一个包含用户ID的匿名对象
        //            var data = new { userId = UserHelper.UserID };

        //            // 将对象序列化为 JSON 字符串
        //            string json = JsonConvert.SerializeObject(data);

        //            // 创建 StringContent 对象，设置其内容和 Content-Type
        //            HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
        //            HttpResponseMessage res = await client.PostAsync($"{DataHelper.BaseConfig.HttpUrl}/tradeamountlimit/userlatestriskinfo", content);
        //            // 设置更长的超时
        //            //client.Timeout = TimeSpan.FromSeconds(60);
        //            string tmp;
        //            if (res.StatusCode == HttpStatusCode.OK)
        //            {
        //                tmp = await res.Content.ReadAsStringAsync();

        //                // 解析 JSON 字符串
        //                JObject jsonObj = JObject.Parse(tmp);

        //                // 获取 value 字段的内容
        //                JObject valueObj = (JObject)jsonObj["value"];

        //                // 解析并访问 value 字段中的属性
        //                int maxvolume = (int)valueObj["maxVolume"];
        //                int currentBid = (int)valueObj["currentBid"];
        //                int currentOffer = (int)valueObj["currentOffer"];
        //                decimal minProfitAlltime = (decimal)valueObj["minProfitAlltime"];
        //                decimal minProfitDaily = (decimal)valueObj["minProfitDaily"];
        //                decimal minBackDaily = (decimal)valueObj["minBackDaily"];
        //                decimal profitAlltime = (decimal)valueObj["profitAlltime"];
        //                decimal solidProfit = (decimal)valueObj["solidProfit"];
        //                decimal floatProfit = (decimal)valueObj["floatProfit"];
        //                decimal totalFee = (decimal)valueObj["totalFee"];
        //                int back = (int)valueObj["back"];
        //                int limitBid = (int)valueObj["limitBid"];
        //                int limitOffer = (int)valueObj["limitOffer"];
        //                // 比较新的 FloatProfit 和上一次的 FloatProfit
        //                if (previousFloatProfit.HasValue && previousFloatProfit.Value != floatProfit)
        //                {
        //                    Messenger.Default.Send("null", MessageToken.RefreshWeiPing);
        //                }

        //                // 更新上一次的 FloatProfit
        //                previousFloatProfit = floatProfit;
        //                // 使用 Dispatcher.InvokeAsync 刷新 UI
        //                PrismApplication.Current.Dispatcher.InvokeAsync(() =>
        //                {
        //                    this.MaxVolume = maxvolume;
        //                    this.MinProfitAllTime = minProfitAlltime;
        //                    this.ProfitAllTime = profitAlltime;
        //                    this.SolidProfit = solidProfit;

        //                    this.CurrentBid = currentBid;
        //                    this.MinProfitDaily = minProfitDaily;
        //                    this.FloatProfit = floatProfit;

        //                    this.CurrentOffer = currentOffer;
        //                    this.MinBackDaily = minBackDaily;

        //                    this.LimitBid = limitBid;
        //                    this.LimitOffer = limitOffer;
        //                    this.Back = back;

        //                    this.TotalFee = totalFee;
        //                });
        //            }
        //        }
        //    }
        //    catch(Exception ex)
        //    {
        //        AppLog.WriteError("RefreshDailyStatus异常" + ex.Message + ex.StackTrace);
        //    }
        //}
        #endregion

    }
}
